package com.linkoog.devtools.intellij.ui.table.cell_editor;

import com.intellij.openapi.util.Iconable;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.EnumComboBoxModel;
import com.intellij.ui.PopupMenuListenerAdapter;
import com.intellij.ui.SimpleListCellRenderer;
import com.intellij.util.ListWithSelection;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import java.awt.*;
import java.util.Collections;

public class ComboBoxTableCellEditor extends JComboBoxTableCellEditor {


    private final JComboBox comboBox;

    public ComboBoxTableCellEditor(@NotNull Class<? extends Enum> en) {
        //noinspection unchecked
        super(new JComboBox(en != null? new EnumComboBoxModel(en): new CollectionComboBoxModel(Collections.emptyList())));
        comboBox = getComponent();

        // problem: pop-up opened - closed by esc - editing is not canceled, but must be
        comboBox.addPopupMenuListener(new PopupMenuListenerAdapter() {
            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                cancelCellEditing();
            }

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
                cancelCellEditing();
            }
        });

        comboBox.setRenderer(SimpleListCellRenderer.create((label, value, index) -> {
            label.setIcon(value instanceof Iconable ? ((Iconable)value).getIcon(Iconable.ICON_FLAG_VISIBILITY) : null);
            label.setText(value == null ? "" : value.toString());
        }));
    }


    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        if (value instanceof ListWithSelection) {
            ListWithSelection options = (ListWithSelection)value;
            comboBox.setModel(new CollectionComboBoxModel(options));

            if (options.getSelection() == null) {
                options.selectFirst();
            }
            comboBox.setSelectedItem(options.getSelection());
        } else {
            Enum enumValue = (Enum)value;
            Class enumClass = enumValue.getDeclaringClass();
            ComboBoxModel model = comboBox.getModel();
            if (!(model instanceof EnumComboBoxModel && model.getSize() > 0 && ((Enum)model.getElementAt(0)).getDeclaringClass() == enumClass)) {
                //noinspection unchecked
                comboBox.setModel(new EnumComboBoxModel(enumClass));
            }
            comboBox.setSelectedItem(value);
        }

        return comboBox;
    }
}
